//
//  SocialPongMainScene.mm
//  SocialPong
//
//  Created by stacie on 8/21/10.
//  Copyright __MyCompanyName__ 2010. All rights reserved.
//
// Audio: pongblipG5.wav from NoiseCollector on www.freesound.org (download file: 4379__NoiseCollector__pongblipG5.wav)
// and pongblipD5.wav also from NoiseCollector on www.freesound.org (download file: 4385__NoiseCollector__pongblipD5.wav)


// Import the interfaces
#import "SocialPongScene.h"
#include <cstdio>

//Pixel to metres ratio. Box2D uses metres as the unit for measurement.
//This ratio defines how many pixels correspond to 1 Box2D "metre"
//Box2D is optimized for objects of 1x1 metre therefore it makes sense
//to define the ratio so that your most common object type is 1x1 metre.
#define PTM_RATIO 32

// enums that will be used as tags
enum {
    spBall = 0,
    spLeftPaddle = 1,
    spRightPaddle = 2,
    spTopWall = 3,
    spBottomWall =4,
    spLeftWall = 5,
    spRightWall = 6,
};


// SocialPong implementation
@implementation SocialPong

@synthesize receivedData;
@synthesize officialVotes;

+(id) scene
{
	// 'scene' is an autorelease object.
	CCScene *scene = [CCScene node];
	
	// 'layer' is an autorelease object.
	SocialPong *layer = [SocialPong node];
	
	// add layer as a child to scene
	[scene addChild: layer];
	
	// return the scene
	return scene;
}

// initialize your instance here
-(id) init
{
	if( (self=[super init])) {
        // enable touches
		self.isTouchEnabled = YES;
        _scoreLeft = 0;
        _scoreRight = 0;
        _scoreMax = 3;      // only 3 points to win for testing!
        _lastHitObj = -1;
        _speedLeft = 0;
        _speedRight = 0;
        _speedMin = -10;
        _speedMax = 10;
        
        
        
        CGSize winSize = [CCDirector sharedDirector].winSize;
        
        // Create a world
        b2Vec2 gravity = b2Vec2(0.0f, 0.0f);    // no gravity
        bool doSleep = true;                    // This will speed up the physics simulation
        _world = new b2World(gravity, doSleep);
        
        // Create edges around the entire screen
        b2BodyDef groundBodyDef;            // Define the ground body.
        groundBodyDef.position.Set(0,0);    // bottom-left corner

        // Call the body factory which allocates memory for the ground body
        // from a pool and creates the ground box shape (also from a pool).
        // The body is also added to the world.
        _groundBody = _world->CreateBody(&groundBodyDef);
        
        b2PolygonShape groundBox;           // Define the ground box shape.
        b2FixtureDef groundBoxDef;
        groundBoxDef.shape = &groundBox;
        
        groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
        _bottomFixture = _groundBody->CreateFixture(&groundBoxDef);
        
        groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), 
                            b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
        _topFixture = _groundBody->CreateFixture(&groundBoxDef);
        
/*        //groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
        //_leftWallFixture = _groundBody->CreateFixture(&groundBoxDef);
        //groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), 
        //                    b2Vec2(winSize.width/PTM_RATIO, 0));
        //_rightWallFixture = _groundBody->CreateFixture(&groundBoxDef);   */
        
        // Create sprite and add it to the layer
        _ball = [CCSprite spriteWithFile:@"ball.png" 
                                             rect:CGRectMake(0, 0, 32, 32)];
        _ball.position = ccp(winSize.width/2, winSize.height/2);
        _ball.tag = (int)spBall;
        [self addChild:_ball];
        
        // Create ball body 
        b2BodyDef ballBodyDef;
        ballBodyDef.type = b2_dynamicBody;
        ballBodyDef.position.Set(winSize.width/(2*PTM_RATIO), winSize.height/(2*PTM_RATIO));
        ballBodyDef.userData = _ball;
        b2Body * ballBody = _world->CreateBody(&ballBodyDef);
        
        // Create ball shape
        b2PolygonShape ballShape;
        ballShape.SetAsBox(_ball.contentSize.width/PTM_RATIO/2, _ball.contentSize.height/PTM_RATIO/2);
        
        // Create shape definition and add to body
        b2FixtureDef ballShapeDef;
        ballShapeDef.shape = &ballShape;
        ballShapeDef.density = 1.0f;
        ballShapeDef.friction = 0.f;
        ballShapeDef.restitution = 1.0f;
        _ballFixture = ballBody->CreateFixture(&ballShapeDef);
		
        b2Vec2 force = b2Vec2(10, 10);
        ballBody->ApplyLinearImpulse(force, ballBodyDef.position);
        _ballStartingPos = ballBodyDef.position;
        
        // Create and add paddles
        [self addPaddle:winSize withId:(int)spLeftPaddle];
        [self addPaddle:winSize withId:(int)spRightPaddle];
        
        [self addScores];   // add the scores
        
        // Create contact listener
        _contactListener = new MyContactListener();
        _world->SetContactListener(_contactListener);
                                
        [self schedule:@selector(tick:)];
        
/*		
		world->SetContinuousPhysics(true);
		
		// Debug Draw functions
		m_debugDraw = new GLESDebugDraw( PTM_RATIO );
		world->SetDebugDraw(m_debugDraw);
		
		uint32 flags = 0;
		flags += b2DebugDraw::e_shapeBit;
//		flags += b2DebugDraw::e_jointBit;
//		flags += b2DebugDraw::e_aabbBit;
//		flags += b2DebugDraw::e_pairBit;
//		flags += b2DebugDraw::e_centerOfMassBit;
		m_debugDraw->SetFlags(flags);		
		
		CCLabel *label = [CCLabel labelWithString:@"Tap screen" fontName:@"Marker Felt" fontSize:32];
		[self addChild:label z:0];
		[label setColor:ccc3(0,0,255)];
		label.position = ccp( screenSize.width/2, screenSize.height-50);
*/
		
		[NSTimer scheduledTimerWithTimeInterval:1.0
										 target:self
									   selector:@selector(getServerVotes)
									   userInfo:nil
										repeats:YES];
		
		
        
	}
	return self;
}

-(void) addScores
{
    // ask director the the window size
    CGSize size = [[CCDirector sharedDirector] winSize];

    // create, position and add label for left side
    _scoreLabelLeft = [CCLabel labelWithString:@"0" fontName:@"Arial" fontSize:90];
    _scoreLabelLeft.position =  ccp( size.width * 0.25 , size.height * 0.9 );
    [self addChild: _scoreLabelLeft];
    
    // create, position and add label for right side -- Marker Felt
    _scoreLabelRight = [CCLabel labelWithString:@"0" fontName:@"Arial" fontSize:90];
    _scoreLabelRight.position =  ccp( size.width * 0.75 , size.height * 0.9 );
    [self addChild: _scoreLabelRight];
    
    // add speed info here too:
    _speedLabelLeft = [CCLabel labelWithString:@"Blue speed: 0" fontName:@"Arial" fontSize:32];
    _speedLabelLeft.position =  ccp( size.width * 0.25 , size.height * 0.1 );
    [self addChild: _speedLabelLeft];
    _speedLabelRight = [CCLabel labelWithString:@"Red speed: 0" fontName:@"Arial" fontSize:32];
    _speedLabelRight.position =  ccp( size.width * 0.75 , size.height * 0.1 );
    [self addChild: _speedLabelRight];
}

-(void) addPaddle: (CGSize)winSize withId:(int)paddleId
{
        
    int tagId = paddleId;
    CGFloat xpos = 0.0;
    
    // Create paddle and add it to the layer    
    //CCSprite *paddle = [CCSprite spriteWithFile:@"vPaddle.png"];
    CCSprite *paddle;
    //paddle = [CCSprite spriteWithFile:@"vPaddle.png"];
    if (tagId == (int)spLeftPaddle) {
        paddle = [CCSprite spriteWithFile:@"blue.png"];
        xpos = paddle.contentSize.width/2;
    } else {
        paddle = [CCSprite spriteWithFile:@"red.png"];
        xpos = winSize.width - (paddle.contentSize.width/2);
    }
    paddle.tag = tagId;
    
    paddle.position = ccp(xpos, winSize.height/2);
    [self addChild:paddle];
    
    // Create paddle body
    b2BodyDef paddleBodyDef;
    paddleBodyDef.type = b2_dynamicBody;
    paddleBodyDef.position.Set(xpos/PTM_RATIO, winSize.height/2/PTM_RATIO);
    paddleBodyDef.userData = paddle;
    if (tagId == (int)spLeftPaddle) { // left paddle
        _leftPaddleBody = _world->CreateBody(&paddleBodyDef);   
    } else {    // right paddle
        _rightPaddleBody = _world->CreateBody(&paddleBodyDef);
    }
    
    // Create paddle shape
    b2PolygonShape paddleShape;
    paddleShape.SetAsBox(paddle.contentSize.width/PTM_RATIO/2, 
                         paddle.contentSize.height/PTM_RATIO/2);
    
    // Create shape definition and add to body
    b2FixtureDef paddleShapeDef;
    paddleShapeDef.shape = &paddleShape;
    paddleShapeDef.density = 10.0f;
    paddleShapeDef.friction = 0.4f;
    paddleShapeDef.restitution = 0.1f;
    if (tagId == (int)spLeftPaddle) { // left paddle
        _leftPaddleFixture = _leftPaddleBody->CreateFixture(&paddleShapeDef);
    } else {    // right paddle
        _rightPaddleFixture = _rightPaddleBody->CreateFixture(&paddleShapeDef);
    }
    
    // Restrict paddle along the y axis
    b2PrismaticJointDef jointDef;
    b2Vec2 worldAxis(0.0f, 1.0f);
    jointDef.collideConnected = true;
    if (tagId == (int)spLeftPaddle) { // left paddle
        jointDef.Initialize(_leftPaddleBody, _groundBody, 
                            _leftPaddleBody->GetWorldCenter(), worldAxis);
    } else {    // right paddle
        jointDef.Initialize(_rightPaddleBody, _groundBody, 
                            _rightPaddleBody->GetWorldCenter(), worldAxis);
    }
    _world->CreateJoint(&jointDef);    
}

- (void)getServerVotes {
	
	NSURL *url = [[NSURL alloc] initWithString:@"http://socialpong.heroku.com/status"];
	NSURLRequest *theRequest = [NSURLRequest requestWithURL:url];
	NSURLConnection	*theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
	
	if (theConnection) {
		receivedData = [[NSMutableData data] retain];
		
	} else {
		NSLog(@"the conn did not work");
		
	}
	
}

/*
-(void) addBottomPaddle: (CGSize)winSize withFilename:(NSString *)fname
{
    // Create paddle and add it to the layer
    CCSprite *paddle = [CCSprite spriteWithFile:fname];
    paddle.position = ccp(winSize.width/2, 50);
    [self addChild:paddle];
    
    // Create paddle body
    b2BodyDef paddleBodyDef;
    paddleBodyDef.type = b2_dynamicBody;
    paddleBodyDef.position.Set(winSize.width/2/PTM_RATIO, 50/PTM_RATIO);
    paddleBodyDef.userData = paddle;
    _paddleBody = _world->CreateBody(&paddleBodyDef);
    
    // Create paddle shape
    b2PolygonShape paddleShape;
    paddleShape.SetAsBox(paddle.contentSize.width/PTM_RATIO/2, 
                         paddle.contentSize.height/PTM_RATIO/2);
    
    // Create shape definition and add to body
    b2FixtureDef paddleShapeDef;
    paddleShapeDef.shape = &paddleShape;
    paddleShapeDef.density = 10.0f;
    paddleShapeDef.friction = 0.4f;
    paddleShapeDef.restitution = 0.1f;
    _paddleFixture = _paddleBody->CreateFixture(&paddleShapeDef);
    
    // Restrict paddle along the x axis
    b2PrismaticJointDef jointDef;
    b2Vec2 worldAxis(1.0f, 0.0f);
    jointDef.collideConnected = true;
    jointDef.Initialize(_paddleBody, _groundBody, 
                        _paddleBody->GetWorldCenter(), worldAxis);
    _world->CreateJoint(&jointDef);    
}
 */

/*
-(void) draw
{
	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states:  GL_VERTEX_ARRAY, 
	// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	
	world->DrawDebugData();
	
	// restore default GL states
	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

}

-(void) addNewSpriteWithCoords:(CGPoint)p
{
	CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);
	CCSpriteSheet *sheet = (CCSpriteSheet*) [self getChildByTag:kTagSpriteSheet];
	
	//We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
	//just randomly picking one of the images
	int idx = (CCRANDOM_0_1() > .5 ? 0:1);
	int idy = (CCRANDOM_0_1() > .5 ? 0:1);
	CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(32 * idx,32 * idy,32,32)];
	[sheet addChild:sprite];
	
	sprite.position = ccp( p.x, p.y);
	
	// Define the dynamic body.
	//Set up a 1m squared box in the physics world
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;

	bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
	bodyDef.userData = sprite;
	b2Body *body = world->CreateBody(&bodyDef);
	
	// Define another box shape for our dynamic body.
	b2PolygonShape dynamicBox;
	dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
	
	// Define the dynamic body fixture.
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &dynamicBox;	
	fixtureDef.density = 1.0f;
	fixtureDef.friction = 0.3f;
	body->CreateFixture(&fixtureDef);
}
*/

-(void)playPing{
    // setup sound
    
    NSString *sndpath = [[NSBundle mainBundle]
                         pathForResource:@"pongblipD5" ofType:@"wav"];
    CFURLRef baseURL = (CFURLRef)[NSURL fileURLWithPath:sndpath];
    
    // Identify it as not a UI Sound
    AudioServicesCreateSystemSoundID(baseURL, &_pingFx);
    AudioServicesPropertyID flag = 0;  // 0 means always play
    AudioServicesSetProperty(kAudioServicesPropertyIsUISound,
                             sizeof(SystemSoundID), &_pingFx, sizeof(AudioServicesPropertyID),
                             &flag);
    AudioServicesPlaySystemSound(_pingFx);
}

-(void)playBuzz{
    // setup sound
    
    NSString *sndpath = [[NSBundle mainBundle]
                         pathForResource:@"pongblipG5" ofType:@"wav"];
    CFURLRef baseURL = (CFURLRef)[NSURL fileURLWithPath:sndpath];
    
    // Identify it as not a UI Sound
    AudioServicesCreateSystemSoundID(baseURL, &_buzzFx);
    AudioServicesPropertyID flag = 0;  // 0 means always play
    AudioServicesSetProperty(kAudioServicesPropertyIsUISound,
                             sizeof(SystemSoundID), &_buzzFx, sizeof(AudioServicesPropertyID),
                             &flag);
    AudioServicesPlaySystemSound(_buzzFx);
}

- (void)tick:(ccTime) dt {
    //_world->Step(dt, 10, 10);    
    _world->Step(dt, 8, 1); 
    //_world->Step(float32 timeStep, <#int32 velocityIterations#>, <#int32 positionIterations#>)

    CGSize size = [[CCDirector sharedDirector] winSize];     // ask director the the window size

    for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {    
        if (b->GetUserData() != NULL) {
            CCSprite *sprite = (CCSprite *)b->GetUserData();                        
            if (sprite.tag == (int)spBall) {
                // constrain ball speed so it doesn't go crazy
                static int maxSpeed = 20;   
                b2Vec2 velocity = b->GetLinearVelocity();
                float32 speed = velocity.Length();
                if (speed > maxSpeed) {
                    b->SetLinearDamping(0.25);
                } else if (speed < maxSpeed) {
                    b->SetLinearDamping(0.0);
                }  

                // check to see if ball went off screen on left or right:
                if (sprite.position.x < 0) {
                    [self checkScoreUpdate:(int)spLeftWall withMessage:@"Ball went left -- right team scores"];
                    float32 b2Angle = -1.1 * CC_DEGREES_TO_RADIANS(sprite.rotation);
                    b->SetTransform(_ballStartingPos, b2Angle);
                    _lastHitObj = -1;
                } else if (sprite.position.x > size.width) {
                    [self checkScoreUpdate:(int)spRightWall withMessage:@"Ball went right -- left team scores"];
                    float32 b2Angle = -1.1 * CC_DEGREES_TO_RADIANS(sprite.rotation);
                    b->SetTransform(_ballStartingPos, b2Angle);
                    _lastHitObj = -1;
                }
            }
            
            sprite.position = ccp(b->GetPosition().x * PTM_RATIO,
                                  b->GetPosition().y * PTM_RATIO);
            //sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
        }        
    }
    std::vector<MyContact>::iterator pos;
    for(pos = _contactListener->_contacts.begin(); 
        pos != _contactListener->_contacts.end(); ++pos) {
        MyContact contact = *pos;
        
        if ((contact.fixtureA == _bottomFixture && contact.fixtureB == _ballFixture) ||
            (contact.fixtureA == _ballFixture && contact.fixtureB == _bottomFixture))
        {
            [self checkPing:(int)spBottomWall withMessage:@"Ball hit bottom!"];
        } else if ((contact.fixtureA == _topFixture && contact.fixtureB == _ballFixture) ||
            (contact.fixtureA == _ballFixture && contact.fixtureB == _topFixture))
        {
            [self checkPing:(int)spTopWall withMessage:@"Ball hit top!"];
        } else if ((contact.fixtureA == _leftPaddleFixture && contact.fixtureB == _ballFixture) ||
            (contact.fixtureA == _ballFixture && contact.fixtureB == _leftPaddleFixture))
        {
            [self checkPing:(int)spLeftPaddle withMessage:@"Ball hit left paddle!"];
        } else if ((contact.fixtureA == _rightPaddleFixture && contact.fixtureB == _ballFixture) ||
            (contact.fixtureA == _ballFixture && contact.fixtureB == _rightPaddleFixture)) {
            [self checkPing:(int)spRightPaddle withMessage:@"Ball hit right paddle!"];
        }
    }    
}

-(void) checkPing: (int)nextObj withMessage:(NSString *)logMsg
{
    if (_lastHitObj == nextObj)
        return;
    else {
        //NSLog(logMsg);
        _lastHitObj = nextObj;
        // Play a sound!
        //[[SimpleAudioEngine sharedEngine] playEffect:@"pongblipG5.wav"];
        [self playPing];
    }
}

-(void) checkScoreUpdate: (int)nextObj withMessage:(NSString *)logMsg
{
    if (_lastHitObj == nextObj)
        return;
    else {
        float velocityFactor = 1.1;
        if (nextObj == (int)spLeftWall) // right team scores
        {
            _scoreRight++; // point for the right team!
            [_scoreLabelRight setString: [[NSNumber numberWithInt:_scoreRight] stringValue]];
            velocityFactor = -1.1;
        } else {        // left team scores
            _scoreLeft++; // point for the left team!
            [_scoreLabelLeft setString: [[NSNumber numberWithInt:_scoreLeft] stringValue]];
        }        
        [self playBuzz];    // Play a sound
        //[self resetBall:velocityFactor];
        //NSLog(logMsg);
        _lastHitObj = nextObj;
        
    }
}

- (void)resetBall:(float)velocityFactor
{
    // NOTE: this does not work -- actually need to do a transform on the ball body
    // ask director the the window size
    CGSize size = [[CCDirector sharedDirector] winSize];
    _ball.position = ccp(size.width/2, size.height/2);
    //ballBodyDef.position.Set(size.width/(2*PTM_RATIO), size.height/(2*PTM_RATIO));
}


/*
-(void) tick: (ccTime) dt
{
	//It is recommended that a fixed time step is used with Box2D for stability
	//of the simulation, however, we are using a variable time step here.
	//You need to make an informed choice, the following URL is useful
	//http://gafferongames.com/game-physics/fix-your-timestep/
	
	int32 velocityIterations = 8;
	int32 positionIterations = 1;
	
	// Instruct the world to perform a single step of simulation. It is
	// generally best to keep the time step and iterations fixed.
	world->Step(dt, velocityIterations, positionIterations);

	
	//Iterate over the bodies in the physics world
	for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
	{
		if (b->GetUserData() != NULL) {
			//Synchronize the AtlasSprites position and rotation with the corresponding body
			CCSprite *myActor = (CCSprite*)b->GetUserData();
			myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
			myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
		}	
	}
}
*/

- (void)setPaddleSpeed:(int) paddleId {
    for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {    
        if (b->GetUserData() != NULL) {
            CCSprite *sprite = (CCSprite *)b->GetUserData();                        
            if (sprite.tag == paddleId) {      // set paddle speed
                //static int maxSpeed = 10;
                
                b2Vec2 velocity = b->GetLinearVelocity();
                //float32 speed = velocity.Length();
                if (paddleId == (int)spLeftPaddle) {
                    b->SetLinearVelocity(b2Vec2(velocity.x, _speedLeft));
                    NSLog(@"setting left speed to %d", _speedLeft);
                    [_speedLabelLeft setString: [NSString stringWithFormat:@"Blue speed: %d", _speedLeft]];
                } else if (paddleId == (int)spRightPaddle) {
                    b->SetLinearVelocity(b2Vec2(velocity.x, _speedRight));
                    NSLog(@"setting right speed to %d", _speedRight);
                    [_speedLabelRight setString: [NSString stringWithFormat:@"Red speed: %d", _speedRight]];
                }
                //if (speed > maxSpeed) {
                //    b->SetLinearDamping(0.5);
                //} else if (speed < maxSpeed) {
                //    b->SetLinearDamping(0.0);
                //}
            }
        }
    }
                
}

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    
    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);

    NSLog(@"touch: %f , %f)", location.x, location.y);
    CGSize size = [[CCDirector sharedDirector] winSize];     // ask director the the window size
    if (location.x < size.width / 2) {
        if (location.y < size.height / 2) {
            NSLog(@"left down");
            if (_speedLeft > _speedMin) {
                _speedLeft = MAX(_speedMin, _speedLeft - 1);
                [self setPaddleSpeed:(int)spLeftPaddle];
            }
        } else {
            NSLog(@"left up");
            if (_speedLeft < _speedMax) {
                _speedLeft = MIN(_speedMax, _speedLeft + 1);
                [self setPaddleSpeed:(int)spLeftPaddle];
            }
        }
    } else {
        if (location.y < size.height / 2) {
            NSLog(@"right down");
            if (_speedRight > _speedMin) {
                _speedRight = MAX(_speedMin, _speedRight - 1);;
                [self setPaddleSpeed:(int)spRightPaddle];
            }
        } else {
            NSLog(@"right up");
            if (_speedRight < _speedMax) {
                _speedRight = MIN(_speedMax, _speedRight + 1);;
                [self setPaddleSpeed:(int)spRightPaddle];
            }
        }
    }


    if (_mouseJoint != NULL) return;
    
    
    if (_leftPaddleFixture->TestPoint(locationWorld)) {
        b2MouseJointDef md;
        md.bodyA = _groundBody;
        md.bodyB = _leftPaddleBody;
        md.target = locationWorld;
        md.collideConnected = true;
        md.maxForce = 1000.0f * _leftPaddleBody->GetMass();
        
        _mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
        _leftPaddleBody->SetAwake(true);
    }
    if (_rightPaddleFixture->TestPoint(locationWorld)) {
        b2MouseJointDef md;
        md.bodyA = _groundBody;
        md.bodyB = _rightPaddleBody;
        md.target = locationWorld;
        md.collideConnected = true;
        md.maxForce = 1000.0f * _rightPaddleBody->GetMass();
        
        _mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
        _rightPaddleBody->SetAwake(true);
    }
    
}

-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    
    if (_mouseJoint == NULL) return;
    
    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
    
    _mouseJoint->SetTarget(locationWorld);
    
}

-(void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    
    if (_mouseJoint) {
        _world->DestroyJoint(_mouseJoint);
        _mouseJoint = NULL;
    }
    
}

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (_mouseJoint) {
        _world->DestroyJoint(_mouseJoint);
        _mouseJoint = NULL;
    }  
}

#pragma mark - 
#pragma mark NSURL delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
	[receivedData setLength:0];	
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
	[receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	[connection release];	
    [receivedData release];
	
	// inform the user
	
    NSLog(@"Connection failed! Error - %@ %@",
		  [error localizedDescription],
		  [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
	NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);	
	[self parseResult];	
}

-(void)parseResult{
	NSString *stringData = [[[NSString alloc] initWithData:receivedData encoding:[NSString defaultCStringEncoding]] autorelease];
	NSArray *voteArray = [stringData componentsSeparatedByString:@","];
	NSLog(@"the voteDump: %@", voteArray);
	self.officialVotes = voteArray;
	NSLog(@"off votes: %@", officialVotes);

    // eventually, we can separate this out into a different function
    int diffUpDown = [[officialVotes objectAtIndex:0] intValue] - [[officialVotes objectAtIndex:1] intValue];
    int sumUpDown = [[officialVotes objectAtIndex:0] intValue] + [[officialVotes objectAtIndex:1] intValue];
    if (sumUpDown != 0)
    {
        //int crowdSpeedLeft = (int)(_speedMax * diffUpDown / sumUpDown);
        int crowdSpeedLeft = (int)(_speedMax * 0.1 * (diffUpDown % 10));

        if (crowdSpeedLeft < _speedMin)
            crowdSpeedLeft = _speedMin;
        else if (crowdSpeedLeft > _speedMax)
            crowdSpeedLeft = _speedMax;
        if (_speedLeft != crowdSpeedLeft)
        {
            _speedLeft = crowdSpeedLeft;
            [self setPaddleSpeed:(int)spLeftPaddle];
        }
    }
    diffUpDown = [[officialVotes objectAtIndex:2] intValue] - [[officialVotes objectAtIndex:3] intValue];
    sumUpDown = [[officialVotes objectAtIndex:2] intValue] + [[officialVotes objectAtIndex:3] intValue];
    
    if (sumUpDown != 0)
    {
        //int crowdSpeedRight = (int)(_speedMax * diffUpDown / sumUpDown);
        int crowdSpeedRight = (int)(_speedMax * 0.1 * (diffUpDown % 10));
    
        if (crowdSpeedRight < _speedMin)
            crowdSpeedRight = _speedMin;
        else if (crowdSpeedRight > _speedMax)
            crowdSpeedRight = _speedMax;
        if (_speedRight != crowdSpeedRight)
        {
            _speedRight = crowdSpeedRight;
            [self setPaddleSpeed:(int)spRightPaddle];
        }
    }
}

/*
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	//Add a new body/atlas sprite at the touched location
	for( UITouch *touch in touches ) {
		CGPoint location = [touch locationInView: [touch view]];
		
		location = [[CCDirector sharedDirector] convertToGL: location];
		
		[self addNewSpriteWithCoords: location];
	}
}

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{	
	static float prevX=0, prevY=0;
	
	//#define kFilterFactor 0.05f
#define kFilterFactor 1.0f	// don't use filter. the code is here just as an example
	
	float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
	float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
	
	prevX = accelX;
	prevY = accelY;
	
	// accelerometer values are in "Portrait" mode. Change them to Landscape left
	// multiply the gravity by 10
	b2Vec2 gravity( -accelY * 10, accelX * 10);
	
	world->SetGravity( gravity );
}
*/
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
	// in case you have something to dealloc, do it in this method
    delete _world;
    _world = NULL;
    _groundBody = NULL;
    
    delete _contactListener;
    //delete _pingFx;
    
	//delete m_debugDraw;

	// don't forget to call "super dealloc"
	[super dealloc];
}
@end
